package com.sq.partner.manager.controller;

import java.io.BufferedReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.sq.partner.manager.common.Config;
import com.sq.partner.manager.common.Constants;
import com.sq.partner.manager.common.Result;
import com.sq.partner.manager.mybatis.model.CommamtFee;
import com.sq.partner.manager.mybatis.model.FacadeNewPayment;
import com.sq.partner.manager.mybatis.model.GatewayUser;
import com.sq.partner.manager.service.ExternalPaymentCardService;
import com.sq.partner.manager.service.OutboundNewPayService;
import com.sq.partner.manager.util.DateUtil;
import com.sq.partner.manager.util.FreeMarkerUtil;
import com.sq.partner.manager.util.LogUtil;
import com.sq.partner.manager.util.MD5Util;

/**
 * 出库缴费--集中收款平台支付
 * 
 * @author zhouxx 2019-03-11
 *
 */
@Controller
@RequestMapping("/outbound")
public class OutboundNewPayController {
    private static Logger logger = LogUtil
            .getLog(OutboundNewPayController.class);

    @Resource
    private OutboundNewPayService outboundNewPayService;
    @Resource
    private ExternalPaymentCardService externalPaymentCardService;

    /**
     * 出库缴费---集中收款平台支付
     * 
     * @param session
     * @param commamtId
     * @param model
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/cardNewPay")
    public String cardNewPay(HttpSession session, String commamtId,
            ModelMap model) throws Exception {
        GatewayUser gatewayuser = (GatewayUser) session
                .getAttribute(Constants.SESSION_USER);
        CommamtFee commamtFee = outboundNewPayService.queryForPay(commamtId);
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("payId", commamtId);
        FacadeNewPayment payment = outboundNewPayService.queryNewPayment(map);
        if (null == payment) {
            // 新增
            payment = outboundNewPayService.saveFacadeNewPayment(commamtFee,
                    gatewayuser);
        } else {
            // 如果支付完成则更新出库信息为已缴费
            if (Constants.NEW_PAYMENT_STATUS_2.equals(payment.getTransState())) {
                // 更新出库表
                outboundNewPayService.updatCommamtInfo(payment.getPayId(),
                        commamtFee.getStatus(),
                        Constants.ACTIR_CARD_OUTBOUND_PAY);
                // 调用收付缴费接口
                Result result = externalPaymentCardService.cardNewPayToPayment(
                        payment, gatewayuser.getEmployeeNo(),
                        gatewayuser.getUserCode());
                if ("success".equals(result.getResult())) {
                    // 更新卡单表
                    outboundNewPayService.updateStatusByCommamtId(
                            payment.getPayId(), Constants.ACTIR_CARD_RELATION,
                            Constants.ACTIR_CARD_ACTIVABLE);
                }
                // 返回成功页面
                return "/actirationCard/activatedCard/pay/success";
            }
            // 上述以外
            else {
                // 调用集中收款平台查询接口看是否支付完成
                payment = outboundNewPayService.noPaymentStatusForOut(payment);
                // 如果中收款平台接口查询为已收付
                if (Constants.NEW_PAYMENT_STATUS_2.equals(payment
                        .getTransState())) {
                    // 更新出库表
                    outboundNewPayService.updatCommamtInfo(payment.getPayId(),
                            commamtFee.getStatus(),
                            Constants.ACTIR_CARD_OUTBOUND_PAY);
                    // 调用收付缴费回传接口
                    Result result = externalPaymentCardService
                            .cardNewPayToPayment(payment,
                                    gatewayuser.getEmployeeNo(),
                                    gatewayuser.getUserCode());
                    if ("success".equals(result.getResult())) {
                        // 更新卡单表
                        outboundNewPayService.updateStatusByCommamtId(
                                payment.getPayId(),
                                Constants.ACTIR_CARD_RELATION,
                                Constants.ACTIR_CARD_ACTIVABLE);
                    }
                    // 返回成功页面
                    return "/actirationCard/activatedCard/pay/success";
                }
            }

        }

        Date date = new Date();
        String transDate = DateUtil.format(date, "yyyyMMddHHmmss");
        String transTime = DateUtil.format(date, "HHmmss");
        String transSeq = DateUtil.format(date, "yyyyMMddHHmmssSSS");
        String notifyURL = Config
                .getProp("card.outbound.newcallback.notifyUrl");
        String returnURL = Config
                .getProp("card.outbound.newcallback.returnUrl");
        String key = Config.getProp("card.newpay.key");
        String fixUser = "0";
        String sysCode = Config.getProp("card_code");
        Date expireDate = payment.getExpireDate();
/*        payment.setAmount(new BigDecimal("0.01"));*/
        String expiredate = DateUtil.format(expireDate, "yyyyMMddHHmmss");
        String checkStr = "ApplyEntity=" + payment.getApplyEntity() + "&Cur="
                + "CNY" + "&Description=" + payment.getTitle() + "&ExpireDate="
                + expiredate + "&FixUser=" + fixUser + "&NotifyURL="
                + notifyURL + "&OurAmount=" + payment.getAmount()
                + "&PaymentCode=" + payment.getPaymentCode() + "&RdSeq="
                + payment.getRdSeq() + "&ReturnURL=" + returnURL
                + "&TransDate=" + transDate + "&TransSeq=" + transSeq
                + "&TransSource=" + sysCode + "&TransTime=" + transTime
                + "&Version=" + "1" + "&key=" + key;

        logger.debug("支付checkStr:" + checkStr);
        String S3Sign = MD5Util.md5One(checkStr);
        model.put("fixUser", fixUser);
        model.put("transSource", sysCode);
        model.put("expiredate", expiredate);
        model.put("payUrl", Config.getProp("card.newpay.payUrl"));
        model.put("newPayment", payment);
        model.put("transDate", transDate);
        model.put("transTime", transTime);
        model.put("transSeq", transSeq);
        model.put("S3Sign", S3Sign);
        model.put("notifyURL", notifyURL);
        model.put("returnURL", returnURL);

        return "/actirationCard/activatedCard/pay/newpayment";
    }

    /**
     * 集中收款平台回调---出库缴费
     * 
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/outboundNewCallBack")
    public void newOutboundCallBack(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        logger.info("开始执行:/newOutboundCallBack");

        // 解析集中收款平台缴费信息回调报文
        StringBuilder jb = new StringBuilder();
        String line = null;
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null) {
            jb.append(line);
        }
        logger.info("支付平台回调请求报文:" + jb.toString());
        Document xml = DocumentHelper.parseText(jb.toString());
        Element element = xml.getRootElement();
        String rdSeq = selectSingleNodeByRoot(element, "/ATS/IN/RD/RdSeq");
        String transState = selectSingleNodeByRoot(element,
                "/ATS/IN/RD/TransState");
        String cancelState = selectSingleNodeByRoot(element,
                "/ATS/IN/RD/CancelState");
        String Abstract = selectSingleNodeByRoot(element, "/ATS/IN/RD/Abstract");
        String recChannel = selectSingleNodeByRoot(element,
                "/ATS/IN/RD/RecChannel");
        String payMadeDate = selectSingleNodeByRoot(element,
                "/ATS/IN/RD/PayMadeDate");
        String corpAct = selectSingleNodeByRoot(element, "/ATS/IN/RD/CorpAct");

        Map<String, String> map = new HashMap<String, String>();
        long time1 = System.currentTimeMillis();
        HashMap<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("rdSeq", rdSeq);
        FacadeNewPayment facadepayment = outboundNewPayService
                .queryNewPayment(paramMap);// 查询支付表是否支付成功

        String status = facadepayment.getTransState();
        if (Constants.NEW_PAYMENT_STATUS_2.equals(status)) {
            // 已通知成功
            map.put("TransState", "2");
            map.put("RtnCode", "success");
        } else {
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = sf.parse(payMadeDate);
            facadepayment.setRdSeq(rdSeq);
            facadepayment.setPayType(recChannel);
            facadepayment.setMerid(corpAct);
            facadepayment.setTransState(transState);
            facadepayment.setCancelState(cancelState);
            facadepayment.setPayDate(date);
            facadepayment.setFeedBackDate(new Date());
            facadepayment.setAbstracts(Abstract);
            boolean flag = false;
            try {
                // 更新支付表状态
                flag = outboundNewPayService.updateFacadeNewPay(facadepayment);
                // TODO 收付款状态TransState:1-未收款 2-已收款 3-收款失败 4-收款中 5-收款未知
                // TODO 若返回1 4 5怎么处理?
                map.put("TransState", "2");
                map.put("RtnCode", "success");
            } catch (Exception e) {
                map.put("TransState", "3");
                map.put("ErrorMsg", "支付表更新失败");
                map.put("RtnCode", "exception");
            }
            if ("2".equals(transState) && flag) {
                try {
                    // 更新出库表
                    outboundNewPayService.updatCommamtInfo(
                            facadepayment.getPayId(),
                            Constants.ACTIR_CARD_OUTBOUND_NOPAY,
                            Constants.ACTIR_CARD_OUTBOUND_PAY);
                    Map<String, String> reMap = outboundNewPayService
                            .getEmployeeNoByCommamtId(facadepayment.getPayId());
                    Result result = externalPaymentCardService
                            .cardNewPayToPayment(facadepayment,
                                    reMap.get("EMPLOYEE_NO"),
                                    reMap.get("USER_CODE"));
                    if ("success".equals(result.getResult())) {
                        // 更新卡单表
                        outboundNewPayService.updateStatusByCommamtId(
                                facadepayment.getPayId(),
                                Constants.ACTIR_CARD_RELATION,
                                Constants.ACTIR_CARD_ACTIVABLE);
                    }
                } catch (Exception e) {
                    logger.error(e);
                }
            }
        }

        logger.info("请求[/newOutboundCallBack] 执行时间:"
                + (System.currentTimeMillis() - time1));
        logger.info("完成执行:/newOutboundCallBack");

        // 返回应答报文到集中收款平台
        String transSeq = selectSingleNodeByRoot(element, "/ATS/PUB/TransSeq");
        Date date = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("HHmmsss");
        map.put("TransDate", sdf1.format(date));
        map.put("TransTime", sdf2.format(date));
        map.put("TransSeq", transSeq);
        map.put("RdSeq", rdSeq);
        map.put("RtnMsg", "接收成功");
        String templates = Config.getProp("pay.NotifyRecState.templates");
        String process = FreeMarkerUtil.process(templates, map);
        logger.info("集中收款平台返回回调结果通知报文：" + process);
        response.setCharacterEncoding("utf-8");
        //response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write(process);
        writer.flush();
        writer.close();
    }

    public String selectSingleNodeByRoot(Element root, String path) {
        Node node = root.selectSingleNode(path);
        if (node == null) {
            return "";
        } else {
            return node.getText();
        }
    }

    /**
     * 集中收款平台支付成功同步通知
     * @throws Exception
     */
    @RequestMapping(value = "/outboundNewCallBackCS")
    public String callBackCS()
            throws Exception {
        return "/actirationCard/activatedCard/pay/success";
    }

}